//
// Created by Administrator on 2021/2/22 0022.
//
#include <stdio.h>
#include <sys/types.h>
#include <jni.h>

#ifndef MY_APPLICATION_STREAM_H
#define MY_APPLICATION_STREAM_H


class Stream {
public:
    Stream();

    virtual ~Stream();

    size_t peek(void *buffer, size_t size);

    size_t read(void *buffer, size_t size);

    virtual uint8_t *getRawBufferAddr();

    virtual jobject getRawBuffer();

    virtual int getRawBufferSize();

protected:
    virtual size_t doRead(void *buffer, size_t size) = 0;

private:
    char *mPeekBuffer;
    size_t mPeekSize;
    size_t mPeekOffset;

};

class MemoryStream : public Stream {
public:
    MemoryStream(void *buffer, size_t size, jobject buf) :
            mBuffer((uint8_t *) buffer),
            mRemaining(size),
            mRawBuffer(buf) {}

    virtual uint8_t *getRawBufferAddr();

    virtual jobject getRawBuffer();

    virtual int getRawBufferSize();

protected:
    virtual size_t doRead(void *buffer, size_t size);

private:
    uint8_t *mBuffer;
    size_t mRemaining;
    jobject mRawBuffer;
};

class FileStream : public Stream {

public:
    FileStream(FILE *fd) : mFd(fd) {}

protected:
    virtual size_t doRead(void *buffer, size_t size);

private:
    FILE *mFd;
};

class JavaInputStream : public Stream {

public:
    JavaInputStream(JNIEnv *env, jobject inputStream, jbyteArray byteArray) :
            mEnv(env),
            mInputStream(inputStream),
            mByteArray(byteArray),
            mByteArrayLength(env->GetArrayLength(byteArray)) {}

protected:
    virtual size_t doRead(void *buffer, size_t size);

private:
    JNIEnv *mEnv;
    const jobject mInputStream;
    const jbyteArray mByteArray;
    const size_t mByteArrayLength;
};

jint JavaStream_OnLoad(JNIEnv *env);


#endif //MY_APPLICATION_STREAM_H
